﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace AP_Data_Mudanca_Requisito_02
{
	/// <summary>
	/// Summary description for BusinessDay
	/// </summary>
	public class BusinessDay
	{
		public BusinessDay()
		{
		}

		#region Métodos Públicos

		/// <summary>
		/// Retorna uma lista com os últimos 5 dias úteis
		/// </summary>
		/// <param name="date"></param>
		/// <returns></returns>
		public List<DateTime> getLastFiveBusinessDay( DateTime date )
		{
			List<DateTime> listLastBusinessDays = new List<DateTime>();

			DateTime currentDate = date;

			//Enquanto a lista não tiver o total de dias, adiciona os dias úteis.
			while( listLastBusinessDays.Count != 5 )
			{
				//Data corrente, recebe o dia anterior
				currentDate = currentDate.AddDays( -1 );

				//Se a data for feriado ou não for dia útil, ignora e passa para a próxima data
				if( isHoliday( currentDate ) || !isBusinessDay( currentDate ) )
					continue;
				else
					//Se for dia útil, adiciona na lista
					listLastBusinessDays.Add( currentDate );
			}

			return listLastBusinessDays;
		}

		/// <summary>
		/// Retorna uma lista com os ultimos 7 dias úteis
		/// </summary>
		/// <param name="date"></param>
		/// <returns></returns>
		public List<DateTime> getLastSevenBusinessDay( DateTime date )
		{
			List<DateTime> listLastBusinessDays = new List<DateTime>();

			DateTime currentDate = date;

			if( !validateDateTime( date ) )
				throw new Exception( "A data informada não é válida, por isso não foi possível retornar os últimos 7 dias úteis." );


			//Enquanto a lista não tiver o total de dias, adiciona os dias úteis.
			while( listLastBusinessDays.Count != 7 )
			{
				//Data corrente, recebe o dia anterior
				currentDate = currentDate.AddDays( -1 );

				//Se a data for feriado ou não for dia útil, ignora e passa para a próxima data
				if( isHoliday( currentDate ) || !isBusinessDay( currentDate ) )
					continue;
				else
					//Se for dia útil, adiciona na lista
					listLastBusinessDays.Add( currentDate );
			}

			return listLastBusinessDays;
		}

		/// <summary>
		/// Retorna o último dia útil.
		/// </summary>
		/// <param name="date"></param>
		/// <returns></returns>
		public DateTime getLastBusinessDay( DateTime date )
		{
			if( !validateDateTime( date ) )
				throw new Exception( "Data inválida." );

			DateTime currentDate = date;

			//Enquanto não encontrar o dia util
			while( true )
			{
				//Data corrente, recebe o dia anterior
				currentDate = currentDate.AddDays( -1 );

				//Se a data for feriado ou não for dia útil, ignora e passa para a próxima data
				if( isHoliday( currentDate ) || !isBusinessDay( currentDate ) )
					continue;
				else
					//Se for dia útil, sai do while
					break;
			}

			return currentDate;
		}

		/// <summary>
		/// Retona uma lista com os ultimos 5 dias corridos.
		/// </summary>
		/// <param name="date"></param>
		/// <returns></returns>
		public List<DateTime> getLastFiveDays( DateTime date )
		{

			if( !validateDateTime( date ) )
				throw new Exception( "Não foi possivel os últimos 5 dias corridos, favor informar uma data válida" );

			List<DateTime> listLastDays = new List<DateTime>();

			DateTime currentDate = date;

			//Enquanto a lista não tiver o total de dias, adiciona os dias.
			while( listLastDays.Count != 5 )
			{
				//Data corrente, recebe o dia anterior
				currentDate = currentDate.AddDays( -1 );

				listLastDays.Add( currentDate );
			}

			return listLastDays;
		}


		/// <summary>
		/// Retorna uma lista com os últimos 7 dias corridos.
		/// </summary>
		/// <param name="date"></param>
		/// <returns></returns>
		public List<DateTime> getLastSevenDays( DateTime date )
		{

			if( !validateDateTime( date ) )
				throw new Exception( "Favor informar uma data válida" );

			List<DateTime> listLastDays = new List<DateTime>();

			DateTime currentDate = date;

			//Enquanto a lista não tiver o total de dias, adiciona os dias.
			while( listLastDays.Count != 7 )
			{
				//Data corrente, recebe o dia anterior
				currentDate = currentDate.AddDays( -1 );

				listLastDays.Add( currentDate );
			}

			return listLastDays;
		}

		/// <summary>
		/// Retorna uma lista com os últimos 30 dias corridos.
		/// </summary>
		/// <param name="date"></param>
		/// <returns></returns>
		public List<DateTime> getLastThirtyDays( DateTime date )
		{
			if( !validateDateTime( date ) )
				throw new Exception( "Impossível recuperar os últimos 30 dias corridos  a partir de uma data inválida." );

			List<DateTime> listLastDays = new List<DateTime>();

			DateTime currentDate = date;

			//Enquanto a lista não tiver o total de dias, adiciona os dias.
			while( listLastDays.Count != 30 )
			{
				//Data corrente, recebe o dia anterior
				currentDate = currentDate.AddDays( -1 );

				listLastDays.Add( currentDate );
			}

			return listLastDays;
		}

		/// <summary>
		/// Verifica se a data é um feriado
		/// </summary>
		/// <param name="date"></param>
		/// <returns>True se a data for feriado</returns>
		public bool isHoliday( DateTime date )
		{
			List<DateTime> listHolidays = getListHolidays();

			return listHolidays.Contains( date );

		}

		/// <summary>
		/// Verifica se a data recebida é um dia útil.
		/// </summary>
		/// <param name="date"></param>
		/// <returns>True - Dia útil.</returns>
		public bool isBusinessDay( DateTime date )
		{
			bool result = true;

			switch( date.DayOfWeek )
			{
				case DayOfWeek.Friday:
				case DayOfWeek.Monday:
				case DayOfWeek.Thursday:
				case DayOfWeek.Tuesday:
				case DayOfWeek.Wednesday:
				result = false;
				break;
				case DayOfWeek.Saturday:
				case DayOfWeek.Sunday:
				result = true;
				break;
			}

			return result;
		}

		#endregion

		#region Métodos Privados

		/// <summary>
		/// Recupera a lista de feriados cadastrados
		/// </summary>
		/// <returns>Lista com todas as datas de feriado</returns>
		private List<DateTime> getListHolidays()
		{
			List<DateTime> listHolidays = new List<DateTime>();

			listHolidays.Add( new DateTime( 2012, 01, 01 ) ); // 01/01/2012
			listHolidays.Add( new DateTime( 2012, 02, 21 ) ); // 21/02/2012
			listHolidays.Add( new DateTime( 2012, 12, 25 ) ); // 25/12/2012
			listHolidays.Add( new DateTime( 2012, 12, 31 ) ); // 31/12/2012

			return listHolidays;
		}

		/// <summary>
		/// Valida se a data é válida.
		/// </summary>
		/// <param name="dateTime"></param>
		/// <returns></returns>
		private bool validateDateTime( DateTime dateTime )
		{
			return dateTime.Year.Equals( 2012 );
		}

		#endregion
	}
}
